----------------------------------------------------------------------------------------------------------------------------------------------------
--[[

    物品列表 和 执行逻辑

    inst:PushEvent("hat_got_item",{item = item,owner = owner}) --- 叠堆物品和新物品使用同一事件
    inst:PushEvent("hat_lost_item",{item = item,owner = owner})

    统一使用 update event

]]--
----------------------------------------------------------------------------------------------------------------------------------------------------
--- 参数
----------------------------------------------------------------------------------------------------------------------------------------------------
--- 辅助函数
    local function GetInnerUseMult(inst)
        return inst.components.hutao_com_cosmic_hat_sys_for_item:GetInnerUseMult() or 1
    end
    local function GetItemStackSize(item)
        if item.components.stackable then
            return item.components.stackable.stacksize
        else
            return 1
        end
    end
    local function GetAllSameItemsNum(inst,item_or_prefab)
        if not inst.components.equippable:IsEquipped() then
            return 0
        end
        local prefab = item_or_prefab
        if type(item_or_prefab) == "table" and item_or_prefab.prefab then
            prefab = item_or_prefab.prefab
        end
        if PrefabExists(prefab) == false then
            return 0
        end
        local num = 0
        inst.components.container:ForEachItem(function(item)
            if item and item.prefab == prefab then
                num = num + GetItemStackSize(item)
            end
        end)
        return num
    end
    local function RemoveSingleItem(inst,item_or_prefab)
        local prefab = item_or_prefab
        if type(item_or_prefab) == "table" and item_or_prefab.prefab then
            prefab = item_or_prefab.prefab
        end
        if PrefabExists(prefab) == false then
            return
        end
        local removed_flag = false
        inst.components.container:ForEachItem(function(item)
            if not removed_flag and item and item.prefab == prefab then
                if item.components.stackable then
                    item.components.stackable:Get():Remove()
                else
                    item:Remove()
                end
                removed_flag = true
            end
        end)
    end
----------------------------------------------------------------------------------------------------------------------------------------------------
--- 单个属性逻辑总控制器
    -------------------------------------------------------------------------------------------
    --- 防水
        local function waterproofer_add(inst,item,value)
            inst.__waterproofer_list = inst.__waterproofer_list or {}
            inst.__waterproofer_list[item] = value * GetItemStackSize(item)
            local total = 0            
            for temp_item,v in pairs(inst.__waterproofer_list) do
                if temp_item and temp_item:IsValid() then
                    total = total + v
                end
            end
            inst.components.waterproofer:SetEffectiveness(math.clamp(total,0,1))
        end
        local function waterproofer_remove(inst,item)
            inst.__waterproofer_list = inst.__waterproofer_list or {}
            inst.__waterproofer_list[item] = 0
            local total = 0
            local need_2_clear = false
            for temp_item,v in pairs(inst.__waterproofer_list) do
                if temp_item and temp_item:IsValid() then
                    total = total + v
                else
                    need_2_clear = true
                end
            end
            inst.components.waterproofer:SetEffectiveness(math.clamp(total,0,1))
            if need_2_clear then
                local new_table = {}
                for temp_item,v in pairs(inst.__waterproofer_list) do
                    if temp_item and temp_item:IsValid() and temp_item ~= item then
                        new_table[temp_item] = v
                    end
                end
                inst.__waterproofer_list = new_table
            end
        end
    -------------------------------------------------------------------------------------------
    --- 保暖-散热。  相互抵消。计算结果为负数的时候，为散热。为正数的时候，为保暖
        local function InsulationUpdate(inst)
            local need_2_clear = false
            local total = 0
            for item,v in pairs(inst.___InsulationModifier) do
                if item and item:IsValid() then
                    total = total + v
                else
                    need_2_clear = true
                end
            end
            if total >= 0 then
                inst.components.insulator:SetWinter()
                inst.components.insulator:SetInsulation(math.abs(total))
            else
                inst.components.insulator:SetSummer()
                inst.components.insulator:SetInsulation(math.abs(total))
            end
            if need_2_clear then
                local new_table = {}
                for item,v in pairs(inst.___InsulationModifier) do
                    if item and item:IsValid() then
                        new_table[item] = v
                    end
                end
                inst.___InsulationModifier = new_table
            end
        end
        local function Insulation_Set_Warm(inst,item,value)
           inst.___InsulationModifier = inst.___InsulationModifier or {}
           inst.___InsulationModifier[item] = math.abs(value)
           InsulationUpdate(inst)
        end
        local function Insulation_Set_Cool(inst,item,value)
           inst.___InsulationModifier = inst.___InsulationModifier or {}
           inst.___InsulationModifier[item] = -math.abs(value)
           InsulationUpdate(inst)
        end
        local function Insulation_Remove(inst,item)
            inst.___InsulationModifier = inst.___InsulationModifier or {}
            local new_table = {}
            for temp_item,v in pairs(inst.___InsulationModifier) do
                if temp_item and temp_item:IsValid() and temp_item ~= item then
                    new_table[temp_item] = v
                end
            end
            inst.___InsulationModifier = new_table
            InsulationUpdate(inst)
        end
    -------------------------------------------------------------------------------------------
    --- 位面防御
        local function PlanarDefenseUpdate(inst)
            local total = 0
            local need_2_clear = false
            for item,v in pairs(inst.__PlanarDefenseModifiers) do
                if item and item:IsValid() then
                    total = total + v
                else
                    need_2_clear = true
                end
            end
            total = math.max(0,total)
            inst.components.planardefense:SetBaseDefense(total)
            if need_2_clear then
                local new_table = {}
                for item,v in pairs(inst.__PlanarDefenseModifiers) do
                    if item and item:IsValid() then
                        new_table[item] = v
                    end
                end
                inst.__PlanarDefenseModifiers = new_table
            end
        end
        local function SetPlanarDefense(inst,item,value)
            inst.__PlanarDefenseModifiers = inst.__PlanarDefenseModifiers or {}
            inst.__PlanarDefenseModifiers[item] = value
            PlanarDefenseUpdate(inst)
        end
        local function RemovePlanarDefense(inst,item)
            inst.__PlanarDefenseModifiers = inst.__PlanarDefenseModifiers or {}
            local new_table = {}
            for temp_item,v in pairs(inst.__PlanarDefenseModifiers) do
                if temp_item and temp_item:IsValid() and temp_item ~= item then
                    new_table[temp_item] = v
                end
            end
            inst.__PlanarDefenseModifiers = new_table
            PlanarDefenseUpdate(inst)
        end
    -------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------
--- 物品逻辑
    local item_logic = {
        ----------------------------------------------------------
        --- 木炭 可堆叠
            --[[ 
                每个提供 0.01的火伤系数.和以及3%防水 .木炭 ，每块提供3点保暖系数，0.1格的照明范围
                戴着帽子时，里面的每格煤炭每21秒会减少1个
            ]]--
            ["charcoal"] = {
                update = function(inst,item,owner)
                    local num = GetAllSameItemsNum(inst,item)
                    --- 计时器
                    if inst.__charcoal_remove_task == nil then
                            inst.__charcoal_remove_task = inst:DoPeriodicTask(1,function()
                                -- 帽子没戴
                                if not inst.components.equippable:IsEquipped() then
                                    inst.__charcoal_remove_task:Cancel()
                                    inst.__charcoal_remove_task = nil
                                    return
                                end
                                local time = inst.components.hutao_com_cosmic_hat_sys_for_item:Add("timer.charcoal",1)
                                -- print("charcoal.timer",time)
                                if time >= 21 then
                                    inst.components.hutao_com_cosmic_hat_sys_for_item:Set("timer.charcoal",0)
                                    RemoveSingleItem(inst,item)
                                end
                            end)
                    end
                    --- 灯光
                    if inst.__light_fx and num == 0 then
                        inst.__light_fx:Remove()
                        inst.__light_fx = nil
                    else
                        inst.__light_fx = inst.__light_fx or owner:SpawnChild("minerhatlight")
                        inst.__light_fx.Light:SetRadius(0.5+0.1*num)
                    end
                end,
                got = function(inst,item,owner)                    
                    waterproofer_add(inst,item,0.03)   --- 防水
                    Insulation_Set_Warm(inst,item,GetItemStackSize(item) * 3) -- 保暖。

                    if owner == nil then return end
                    item.__cosmic_hat_stack_event_charcoal = item.__cosmic_hat_stack_event_charcoal or function(item)
                        if inst.components.equippable:IsEquipped() then
                            owner.components.hutao_com_fire_damage:AddAdditiveMultiplier(item,0.01*GetItemStackSize(item))
                        else
                            owner.components.hutao_com_fire_damage:RemoveAdditiveMultiplier(item)
                        end
                    end
                    item.__cosmic_hat_stack_event_charcoal(item)
                    item:ListenForEvent("stacksizechange",item.__cosmic_hat_stack_event_charcoal)
                end,
                lost = function(inst,item,owner)
                    waterproofer_remove(inst,item)   --- 防水
                    Insulation_Remove(inst,item) -- 保暖。
                    if item.__cosmic_hat_stack_event_charcoal then
                        item:RemoveEventCallback("stacksizechange",item.__cosmic_hat_stack_event_charcoal)
                        item.__cosmic_hat_stack_event_charcoal = nil
                    end
                    if owner == nil then return end
                    owner.components.hutao_com_fire_damage:RemoveAdditiveMultiplier(item)
                end,
            },
        ----------------------------------------------------------
        --- 玲珑饰物 . 增加49生命上限，14理智上限，0.14火伤系数，0.14攻击系数,28%防水
            ["hutao_equipment_exquisite_ornament"] = {
                got = function(inst,item,owner)
                    if owner == nil then return end
                    owner.components.hutao_com_max_value_controller:AddTempExtraHealth(item,49)
                    owner.components.hutao_com_max_value_controller:AddTempExtraSanity(item,14)
                    owner.components.hutao_com_fire_damage:AddAdditiveMultiplier(item,0.14)
                    owner.components.combat.externaldamagemultipliers:SetModifier(item,1+0.14)
                    waterproofer_add(inst,item,0.28)   --- 防水
                    if item._exquisite_ornament_finiteuses_task then
                        return
                    end
                    item._exquisite_ornament_finiteuses_task = item:DoPeriodicTask(1,function()
                        item.components.finiteuses:Use(0.5*GetInnerUseMult(inst))
                    end)
                end,
                lost = function(inst,item,owner)
                    if owner == nil then return end
                    owner.components.hutao_com_max_value_controller:RemoveTempExtraHealth(item)
                    owner.components.hutao_com_max_value_controller:RemoveTempExtraSanity(item)
                    owner.components.hutao_com_fire_damage:RemoveAdditiveMultiplier(item)
                    owner.components.combat.externaldamagemultipliers:RemoveModifier(item)
                    waterproofer_remove(inst,item)   --- 防水
                    if item._exquisite_ornament_finiteuses_task then
                        item._exquisite_ornament_finiteuses_task:Cancel()
                        item._exquisite_ornament_finiteuses_task = nil
                    end
                end,
            },
        ----------------------------------------------------------
        --- 梅花（属于食物）：可堆叠，每朵提供49生命上限。
            ["hutao_item_plum_blossom_petal"] = {
                got = function(inst,item,owner)
                    if owner == nil then return end
                    owner.components.hutao_com_max_value_controller:AddTempExtraHealth(item,49*GetItemStackSize(item))
                end,
                lost = function(inst,item,owner)
                    if owner == nil then return end
                    owner.components.hutao_com_max_value_controller:RemoveTempExtraHealth(item)
                end,
            },
        ----------------------------------------------------------
        --- 梅菜扣肉（属于食物）：可堆叠，每个提供5.5/min的饱度回复，并提供11/min的生命恢复。
            ["hutao_cooked_food_braised_pork_belly_with_preserved_vegetable"] = {
                update = function(inst,item,owner)
                    if inst.__braised_pork_belly_with_preserved_vegetable_task then
                        return
                    end
                    inst.__braised_pork_belly_with_preserved_vegetable_task = inst:DoPeriodicTask(1,function()
                        local owner = inst.components.inventoryitem.owner
                        if not inst.components.equippable:IsEquipped() or owner == nil then
                            inst.__braised_pork_belly_with_preserved_vegetable_task:Cancel()
                            inst.__braised_pork_belly_with_preserved_vegetable_task = nil
                            return
                        end
                        local all_stack_num = GetAllSameItemsNum(inst,item)
                        owner.components.hunger:DoDelta(5.5*all_stack_num/60,true)
                        owner.components.health:DoDelta(11*all_stack_num/60,true)
                    end)
                end,
            },
        ----------------------------------------------------------
        --- 梅花酿（属于食物）：可堆叠，每个提供+0.03体温/s，-7san/min，0.14火伤系数。
            -- 变黄的梅花酿额外-3.5san/min，变红的再-3.5san/min
            ["hutao_cooked_food_plum_blossom_wine"] = {
                update = function(inst,item,owner)
                    if inst.__plum_blossom_wine_task then
                        return
                    end
                    local prefab = item.prefab
                    inst.__plum_blossom_wine_task = inst:DoPeriodicTask(1,function()
                        local owner = inst.components.inventoryitem.owner
                        local all_stack_num = GetAllSameItemsNum(inst,prefab)
                        if not inst.components.equippable:IsEquipped() or owner == nil or all_stack_num == 0 then
                            inst.__plum_blossom_wine_task:Cancel()
                            inst.__plum_blossom_wine_task = nil
                            return
                        end
                        owner.components.temperature:DoDelta(0.03*all_stack_num)
                        --- sanity
                        local total_sanity_delta = 0
                        inst.components.container:ForEachItem(function(temp_item)
                            if not (temp_item and temp_item.prefab == prefab) then
                                return
                            end
                            if temp_item:HasTag("fresh") then --- 绿色的
                                total_sanity_delta = total_sanity_delta - 7*GetItemStackSize(inst)
                            elseif temp_item:HasTag("stale") then --- 黄色的
                                total_sanity_delta = total_sanity_delta - 10.5*GetItemStackSize(inst)
                            elseif temp_item:HasTag("spoiled") then --- 红色的
                                total_sanity_delta = total_sanity_delta - 14*GetItemStackSize(inst)
                            end
                        end)
                        owner.components.sanity:DoDelta(total_sanity_delta/60,true)
                    end)
                end,
                got = function(inst,item,owner)
                    if owner == nil then return end
                    owner.components.hutao_com_fire_damage:AddAdditiveMultiplier(item,0.14*GetItemStackSize(item))
                end,
                lost = function(inst,item,owner)
                    if owner == nil then return end
                    owner.components.hutao_com_fire_damage:RemoveAdditiveMultiplier(item)
                end,
            },
        ----------------------------------------------------------
        --- 巡之丘高中校服： 每个提供0.2体力系数a，0.3攻击系数和60点防暑系数.
            ["hutao_equipment_megurigaoka_private_high_school_uniform"] = {
                got = function(inst,item,owner)
                    Insulation_Set_Cool(inst,item,60) --- 散热
                    if item.__cosmic_hat_finiteuses_task == nil then
                        item.__cosmic_hat_finiteuses_task = item:DoPeriodicTask(1,function()
                            item.components.finiteuses:Use(0.5*GetInnerUseMult(inst))
                        end)
                    end
                    if owner == nil then return end
                    owner.components.hutao_com_physical_power:AddModulus(item,0.2)
                    owner.components.combat.externaldamagemultipliers:SetModifier(item,1+0.3)
                end,
                lost = function(inst,item,owner)
                    Insulation_Remove(inst,item)    --- 散热
                    if item.__cosmic_hat_finiteuses_task ~= nil then
                        item.__cosmic_hat_finiteuses_task:Cancel()
                        item.__cosmic_hat_finiteuses_task = nil
                    end
                    if owner == nil then return end
                    owner.components.hutao_com_physical_power:RemoveModulus(item)
                    owner.components.combat.externaldamagemultipliers:RemoveModifier(item)
                end,
            },
        ----------------------------------------------------------
        --- 抑郁少女的黑卫衣：
            --[[
                    帽子里的卫衣数量为X 。
                    帽子提供5X点位面防御。
                    吃食的时候，食物提供的San为Y，增加玩家的Sanity Y*25% *X。
                    X至少为1时，当胡桃身上没有【郁愈域】时，检测身上是否穿着【抑郁少女的黑卫衣】，若没有穿，则按照与卫衣同样的逻辑生成【郁愈域】，护盾量为消耗饱度的X倍。
                ]]
            ["hutao_equipment_black_hoodie_of_a_depressed_girl"] = {
                got = function(inst,item,owner)
                    SetPlanarDefense(inst,item,5) --- 位面防御
                    if owner == nil then return end
                    
                    --- 容器里衣服的数量
                    inst.__get_black_hoodies_in_hat = inst.__get_black_hoodies_in_hat or function()
                        local temp_ret = 0
                        local items = {}
                        inst.components.container:ForEachItem(function(temp_item)
                            if temp_item and temp_item.prefab == item.prefab then
                                temp_ret = temp_ret + 1
                                table.insert(items,temp_item)
                            end
                        end)
                        return temp_ret
                    end
                    --- 检查是否需要生成郁愈域
                    inst.__black_hoodie_timer = inst.__black_hoodie_timer or 0
                    if inst.__black_hoodie_task then
                        inst.__black_hoodie_task:Cancel()
                    end
                    inst.__black_hoodie_task = inst:DoPeriodicTask(1,function()
                        --- 耐久度消耗
                        local black_hoodie_num_in_hat,items = inst.__get_black_hoodies_in_hat()
                        for k, temp_item in pairs(items or {}) do
                            temp_item.components.finiteuses:Use(0.5*GetInnerUseMult(inst))
                        end
                        --- 容器里衣服的数量
                        if black_hoodie_num_in_hat == 0 then
                            inst.__black_hoodie_timer = 0
                            return
                        end
                        -- 当前的郁愈域
                        local current_shell = owner.components.hutao_com_healing_grove:GetCurrent()
                        if current_shell > 0 then
                            inst.__black_hoodie_timer = 0
                            return
                        end
                        ---- 本身穿着衣服
                        local body_item = owner.components.inventory:GetEquippedItem(EQUIPSLOTS.BODY)
                        if body_item and body_item.prefab == item.prefab then
                            inst.__black_hoodie_timer = 0
                            return
                        end
                        inst.__black_hoodie_timer = inst.__black_hoodie_timer + 1
                        if inst.__black_hoodie_timer >= 10 then
                            inst.__black_hoodie_timer = 0
                            local current_hunger = owner.components.hunger.current
                            local value_for_shield = current_hunger*0.75
                            owner.components.hunger:DoDelta(-value_for_shield)
                            owner.components.hutao_com_healing_grove:DoDelta(value_for_shield*black_hoodie_num_in_hat)
                        end
                    end)
                    --- 玩家吃食物事件
                    inst.__black_hoodie_on_eat_event_fn = inst.__black_hoodie_on_eat_event_fn or function(owner,_table)
                        local food = _table and _table.food
                        if food then
                            local mult = 0.5*inst.__get_black_hoodies_in_hat() -- 食物回San的倍率
                            item:PushEvent("player_on_eat",{owner = owner,food = food ,mult = mult})
                        end
                    end
                    inst:ListenForEvent("oneat",inst.__player_eater_event,owner)
                end,
                lost = function(inst,item,owner)
                    RemovePlanarDefense(inst,item) --- 位面防御
                    if inst.__black_hoodie_task then
                        inst.__black_hoodie_task:Cancel()
                        inst.__black_hoodie_task = nil
                    end
                    if inst.__black_hoodie_on_eat_event_fn then
                        inst:RemoveEventCallback("oneat",inst.__black_hoodie_on_eat_event_fn,owner)
                    end
                    if inst.__black_hoodie_on_eat_event_fn then
                        inst:RemoveEventCallback("oneat",inst.__black_hoodie_on_eat_event_fn,owner)
                    end
                end,
            },
        ----------------------------------------------------------
    }
----------------------------------------------------------------------------------------------------------------------------------------------------
-- 功能模块安装
    local function hat_com_install(inst)
        -----------------------------------------------------------------------------
        --- 保暖
            inst:AddComponent("insulator")
            inst.components.insulator:SetInsulation(0)
        -----------------------------------------------------------------------------
        --- 位面防御
            inst:AddComponent("planardefense")
            inst.components.planardefense:SetBaseDefense(0)
        -----------------------------------------------------------------------------
    end
----------------------------------------------------------------------------------------------------------------------------------------------------
return {
    fn = function(inst)
        if not TheWorld.ismastersim then
            return
        end
        inst:ListenForEvent("hat_got_item",function(inst,_table)
            local item = _table.item
            local owner = _table.owner
            local cmd_table = item_logic[item.prefab]
            if item and cmd_table then
                if cmd_table.update then
                    cmd_table.update(inst,item,owner)
                end
                if cmd_table.lost then
                    cmd_table.lost(inst,item,owner)
                end
                if inst.components.equippable:IsEquipped() and cmd_table.got then
                    cmd_table.got(inst,item,owner)
                end
            end
        end)
        inst:ListenForEvent("hat_lost_item",function(inst,_table)
            local item = _table.item
            local owner = _table.owner
            local cmd_table = item_logic[item.prefab]
            if item and cmd_table then
                if cmd_table.update then
                    cmd_table.update(inst,item,owner)
                end
                if cmd_table.lost then
                    cmd_table.lost(inst,item,owner)
                end
            end
        end)
        hat_com_install(inst)
    end,
    item_logic = item_logic,
}